<!--
 * @Author: Bobby
 * @Date: 2021-12-30 10:01:42
 * @LastEditTime: 2023-10-13 10:04:35
 * @LastEditors: 甯左龙 1173405584@qq.com
 * @Description:
 * @FilePath: \wms-v2\src\ve\elements\basic\uiForm\uiForm.vue
 * CIMC-V2
-->
<template>
  <!--  -->
  <div class="ui-form" :class="['overflow-x-hidden overflow-y-auto scrollbar--light']" :style="{ maxHeight: `${layerPageHeight}px` }">
    <el-form
      :id="'uiform_' + info._id"
      :ref="info._id"
      v-ui-ref="vSetRef"
      :inline="true"
      :label-position="info.extension.labelPosition.value"
      :model="selfFormData"
      :rules="setRules"
      :show-message="true"
      status-icon
      @submit.prevent
    >
      <Widget :class="['grid cols-' + info.extension.layout.value]" :list="info.list" />
    </el-form>
    <!-- <div>预览formData:{{ selfFormData }}</div> -->
  </div>
</template>
<script>
  import { defineComponent, defineAsyncComponent } from 'vue'
  import { UiMixin, RefsInjectMixin } from '@ve/mixin'
  import cloneDeep from 'lodash/cloneDeep'
  // import isEmpty from 'lodash/isEmpty'
  import trim from 'lodash/trim'
  import isArray from 'lodash/isArray'
  import { customAlphabet } from 'nanoid'
  import { getModelInfo } from '@ve/utils/getModelInfo'
  import { getComponentDefaulType, processingConstant, getDefaultDate } from '@ve/utils/utils'
  import { domHeight, getBody } from '@ve/utils/domHeight'
  import { ElMessage } from 'element-plus'
  export default defineComponent({
    name: 'UiForm',
    components: {
      // 使用异步组件
      Widget: defineAsyncComponent(() => import('@ve/components/widget.vue')),
    },
    mixins: [UiMixin, RefsInjectMixin],
    provide() {
      return {
        formId: this.info._id,
      }
    },
    props: {
      info: {
        required: true,
        type: Object,
        default: function () {
          return {}
        },
      },
    },
    data() {
      return {
        uiFormBoxHeight: null,
        layerPageHeight: 500,
        lastNewval: {},
        getHasShowScroll: false,
        formItemMap: {}, // 表单项字段描述映射
        // setRules: {},
      }
    },
    computed: {
      selfFormData() {
        return this.info.data.formData
      },
      setRules() {
        const rules = cloneDeep(this.info.rules) || {}
        for (let key in rules) {
          const arr = rules[key] || []

          for (let i = 0; i < arr.length; i++) {
            //临时使用 后期可删除
            if (arr[i].message === 'Ve.utils.请输入必填信息') {
              arr[i].message = '请输入必填信息'
            }
            if (arr[i].pattern) {
              try {
                arr[i].pattern = new RegExp(arr[i].pattern)
              } catch (error) {
                ElMessage({
                  showClose: true,
                  message: `正则解析错误！ --  ${arr[i].pattern}`,
                  type: 'error',
                })
              }
            }
            // 删除多余属性
            if (arr[i].isChecked !== undefined) delete arr[i].isChecked
            if (arr[i]._id) delete arr[i]._id
          }
        }
        return rules
      },
      childrenHasTree() {
        let hasTree = false
        const eachFunc = (obj) => {
          if (obj.type === 'uiTree') hasTree = true
          obj.pageModules &&
            obj.pageModules.forEach((item) => {
              eachFunc(item)
            })
          obj.list &&
            obj.list.forEach((item) => {
              eachFunc(item)
            })
        }
        eachFunc(this.info)

        return hasTree
      },
    },
    watch: {
      // setRules: {
      //   handler() {
      //     console.log('验证规则改变了！！！！！！！！！！！')
      //   },
      // },
      // selfFormData: {
      //   deep: true,
      //   handler(newVal) {
      //     console.log('formData改变了！！！！！！！！！！！', newVal)
      //     // 运行逻辑条件
      //     this.handlerLogicCondition(newVal)
      //   },
      // },
    },
    created() {
      //正则转换
      // const rules = cloneDeep(this.info.rules) || {}
      // for (let key in rules) {
      //   const arr = rules[key] || []
      //   for (let i = 0; i < arr.length; i++) {
      //     if (arr[i].pattern) {
      //       arr[i].pattern = new RegExp(arr[i].pattern)
      //     }
      //   }
      // }
      // console.log(rules)
      // this.setRules = rules
    },
    mounted() {
      // console.log('form this.previewPageId', this.previewPageId(), this.info._id)
      this.$sub(`SplitpaneResized_${this.previewPageId()}`, () => {
        // console.log('表单重新计算高度 -------- ', this.info._id)
        this.getLayerPageHeight()
      })

      this.$nextTick(() => {
        //暂时先timeout一下 后面优化了
        setTimeout(() => {
          this.getLayerPageHeight()
          // 备份_formData
          this.getInfo.data._formData = cloneDeep(this.info.data.formData)
        }, 500)
      })
    },
    activated() {
      this.getLayerPageHeight()
    },
    methods: {
      getLayerPageHeight() {
        setTimeout(() => {
          let _body = getBody(this).find(`#uiform_${this.info._id}`)
          let _domHeight = domHeight(this)
          // console.log('getLayerPageHeight form', this.info._id, this.info.name, { _body: _body.length, _domHeight })
          // console.log('表单高度 -------- ', this.info._id, _domHeight)
          if (_body.length > 0) {
            if (_domHeight > 0) {
              this.layerPageHeight = _domHeight
            }
            //是否有滚动条
            if (_body.length > 0) {
              let uiFormBoxHeight = _body[0].clientHeight
              this.getHasShowScroll = uiFormBoxHeight >= this.layerPageHeight ? true : false
            }
          }
        }, 200)
      },
      dataSourceChange(newval) {
        // console.log('this.dataSource.getDataKey ------ 获取数据key = = ', this.info.dataSourceBind.getDataKey?.value)
        // console.log('newval ---------- 拿到的数据 == ', newval)
        // 判断是否有值改变  --  先不做判断 （开启会导致双击同一条数据不渲染问题）
        // let changeFlag = false
        // Object.keys(newval).map((v) => {
        //   if (newval[v] !== this.lastNewval[v]) {
        //     changeFlag = true
        //   }
        // })
        // if (changeFlag) {
        //   this.lastNewval = cloneDeep(newval)
        // } else {
        //   // 如果值未改变则不进行后续操作
        //   return
        // }

        // 取消timeOut 防止点击打开图层 -》 数据注入 注入值被覆盖
        let _obj = {}
        // 赋默认值
        if (this.getInfo.data.formItems) {
          Object.keys(this.getInfo.data.formItems).forEach((v) => {
            let model_info = getModelInfo(this, v)
            if (isArray(model_info)) return
            if (!model_info) return
            if (model_info && model_info.extension.defaultValue) {
              // console.log(`触发寻找默认值~~~~~~~~${model_info._id} --------------------- ${model_info.extension.defaultValue.value}`)
              _obj[model_info.extension.model.value] = processingConstant(this, model_info.extension.defaultValue.value)
            } else {
              //开关按钮单独获取值
              if (model_info.type === 'uiSwitch') {
                let switchValue = null
                if (model_info.extension.defaultState.value) {
                  switchValue = model_info.extension.activeValue.value
                } else {
                  switchValue = model_info.extension.inactiveValue.value
                }
                _obj[model_info.extension.model.value] = processingConstant(this, switchValue)
              } else if (model_info.type === 'uiDate') {
                // 日期时间组件单独获取值
                if (model_info.extension.defaultDate.value) {
                  // 如果设置默认值为 当前
                  if (model_info.extension.selection.value === 'datetime' || model_info.extension.selection.value === 'date') {
                    // 如果当前组件类型为 datetime 或 date
                    if (model_info.extension.defaultDate.value === 'now') {
                      // 设置 默认值为 当前 的默认值
                      _obj[model_info.extension.model.value] = getDefaultDate('now')
                      // 如果为日期类型则去掉值的时分秒
                      if (model_info.extension.selection.value.indexOf('time') == -1) {
                        _obj[model_info.extension.model.value] = _obj[model_info.extension.model.value].split(' ')[0]
                      }
                    }
                  } else if (model_info.extension.selection.value === 'datetimerange' || model_info.extension.selection.value === 'daterange') {
                    // 如果当前组件类型为 时间范围
                    if (model_info.extension.defaultDate.value !== 'now') {
                      _obj[model_info.extension.model.value] = getDefaultDate(model_info.extension.defaultDate.value)
                      const startSuffix = model_info.extension?.startSuffix?.value ? model_info.extension?.startSuffix?.value : '_start'
                      const endSuffix = model_info.extension?.endSuffix?.value ? model_info.extension?.endSuffix?.value : '_end'
                      _obj[`${model_info.extension.model.value}${startSuffix}`] = _obj[model_info.extension.model.value][0] || ''
                      _obj[`${model_info.extension.model.value}${endSuffix}`] = _obj[model_info.extension.model.value][1] || ''
                      // 如果为日期类型则去掉值的时分秒
                      if (model_info.extension.selection.value.indexOf('time') == -1) {
                        _obj[model_info.extension.model.value][0] = _obj[model_info.extension.model.value][0].split(' ')[0]
                        _obj[model_info.extension.model.value][1] = _obj[model_info.extension.model.value][1].split(' ')[0]
                        _obj[`${model_info.extension.model.value}${startSuffix}`] =
                          _obj[`${model_info.extension.model.value}${startSuffix}`].split(' ')[0]
                        _obj[`${model_info.extension.model.value}${endSuffix}`] =
                          _obj[`${model_info.extension.model.value}${endSuffix}`].split(' ')[0]
                      }
                    }
                  }
                }
              } else {
                _obj[model_info.extension.model.value] = getComponentDefaulType(model_info.type)
              }
            }
          })
        } else {
          // 兼容老的 form 组件 ，如果没有存储 formItems 则调用之前的方法
          Object.keys(this.getInfo.data.formData).map((v) => {
            _obj[v] = ''
          })
        }
        let _mergeData = {}

        // 根据 getDataKey 筛选需要的数据
        if (!trim(this.info.dataSourceBind.getDataKey?.value)) {
          // 如果没有 getDataKey 则返回全量数据
          _mergeData = newval
        } else {
          const keyList = this.info.dataSourceBind.getDataKey?.value.split(',')
          isArray(keyList) &&
            keyList.forEach((item) => {
              item = trim(item)
              if (newval[item] !== undefined) {
                // 如果传过来的对象里面没有要取得值 则丢弃
                _mergeData[item] = newval[item]
              }
            })
        }

        if (this.info.dataSourceBind.getArrayIndex && this.info.dataSourceBind.getArrayIndex.value != 'all') {
          if (_mergeData['data']) {
            _mergeData = _mergeData['data'][this.info.dataSourceBind.getArrayIndex.value]
          }
        }

        // let _data = isEmpty(_mergeData)
        //   ? _obj
        //   : {
        //       ...this.getInfo.data.formData,
        //       ..._mergeData,
        //     }

        let _data = {
          ...this.getInfo.data.formData,
          ..._mergeData,
        }

        // 先查找改变了的值
        // 先取消触发值改变事件
        // const keysList = keys(_data)
        // let changeModelList = []
        // keysList.forEach((keyItem) => {
        //   if (_data[keyItem] !== this.getInfo.data.formData[keyItem]) {
        //     changeModelList.push(keyItem)
        //   }
        // })
        // 赋值
        this.getInfo.data.formData = _data
        this.getInfo.data._formData = cloneDeep(_data)
        // 触发改变了的组件的值改变事件
        // const eachFunc = (obj) => {
        //   const modelVal = obj.extension?.model?.value
        //   // 查找组件的 model 值绑定在修改值对象中
        //   if (modelVal && includes(changeModelList, modelVal)) {
        //     // 触发组件的值改变事件
        //     this.vuiComponents[obj._id]?.self?.onChange()
        //   }
        //   obj.pageModules &&
        //     obj.pageModules.forEach((item) => {
        //       eachFunc(item)
        //     })
        //   obj.list &&
        //     obj.list.forEach((item) => {
        //       eachFunc(item)
        //     })
        // }
        // eachFunc(this.getInfo)
      },
      setFormData(data) {
        this.getInfo.data.formData = Object.assign(this.getInfo.data.formData, data)
      },
      handlerLogicCondition() {
        let conditionResp = true
        const formData = this.selfFormData
        let componentId = (num) => {
          const nanoid = customAlphabet('abcdefghijklmnopqrstuvwsyzABCDEFGHIJKLMN', num)
          return nanoid()
        }
        const logicConditionList = this.info.extension.logicCondition ? cloneDeep(this.info.extension.logicCondition.value) : []
        if (logicConditionList.length) {
          logicConditionList.forEach((conditionItem) => {
            // 如果没有配置 modelKey 或者取到的值为空 则不进行判断
            if (conditionItem.modelKey && (formData[conditionItem.modelKey] || formData[conditionItem.modelKey] === 0)) {
              let runStr = ''
              const b = componentId(6)
              const d = componentId(6)
              window.cacheObj = {}
              window.cacheObj[b] = formData[conditionItem.modelKey]
              if (conditionItem.conditionKey.indexOf('time') > -1) {
                // 如果是比较时间类型的值 则需要将获取到的值转化为时间戳
                window.cacheObj[b] = new Date(formData[conditionItem.modelKey].replace(/-/g, '/')).getTime()
              }
              // 对获取到的消息内容做变量拆分 -- #{}符号包裹内容视为变量
              const staticList = conditionItem.conditionModel.split(/#{.*?}/gi)
              // const variableList = conditionItem.conditionModel.match(/(?<=#{).*?(?=})/g)
              const variableList = conditionItem.conditionModel.match(/#{(.+?)\}/g)
              if (variableList && variableList.length) {
                // 如果有配置变量 则先获取变量值
                let argsIsNull = false // 判断是否有空值 有空值则不做判断
                variableList.forEach((variableItem, index) => {
                  let variableContent = ''
                  variableItem = trim(variableItem.slice(2, -1))
                  if (variableItem.indexOf('->') !== -1) {
                    const fieldList = variableItem.split('->')
                    variableContent = formData
                    fieldList.forEach((fieldItem) => {
                      // 如果没有后续值则不继续往下取值
                      if (variableContent[trim(fieldItem)] === undefined) return
                      variableContent = variableContent[trim(fieldItem)]
                    })
                  } else if (variableItem === '_currentDate') {
                    // 如果是与当前时间做对比 则获取当前时间
                    variableContent = new Date().getTime()
                  } else {
                    variableContent = formData[variableItem]
                    if (conditionItem.conditionKey.indexOf('time') > -1 && variableContent) {
                      // 如果是比较时间类型的值 则需要将获取到的值转化为时间戳
                      variableContent = new Date(variableContent.replace(/-/g, '/')).getTime()
                    }
                  }
                  if (!variableContent && variableContent !== 0) {
                    // 有空值且值不为 0 则记录
                    argsIsNull = true
                  }
                  staticList.splice(index * 2 + 1, 0, variableContent)
                })
                if (argsIsNull) {
                  // 如果有空值 则不进行逻辑判断
                  return
                }
                // window.cacheObj[d] = staticList.join('')
                try {
                  window.cacheObj[d] = Function('"use strict";return (' + staticList.join('') + ')')()
                } catch {
                  window.cacheObj[d] = ''
                }
              } else {
                try {
                  window.cacheObj[d] = Function('"use strict";return (' + conditionItem.conditionModel + ')')()
                } catch {
                  window.cacheObj[d] = ''
                }
                // window.cacheObj[d] = conditionItem.conditionModel
              }
              // 时间类型的比较符需要转换
              if (conditionItem.conditionKey === 'timeGt') conditionItem.conditionKey = '>'
              if (conditionItem.conditionKey === 'timeLt') conditionItem.conditionKey = '<'
              if (conditionItem.conditionKey === 'timeGtEq') conditionItem.conditionKey = '>='
              if (conditionItem.conditionKey === 'timeLtEq') conditionItem.conditionKey = '<='
              runStr = `cacheObj.${b} ${conditionItem.conditionKey} (cacheObj.${d})`
              let respFlag = false
              console.log('runStr -------------- ', runStr)
              console.log('window.cacheObj ----------- ', window.cacheObj)
              try {
                // 执行字符串
                respFlag = Function('"use strict";return (' + runStr + ')')()
              } catch (error) {
                console.log('error', error)
              }

              if (!respFlag) {
                // 取消清空值操作 改为消息提示
                // if (isString(formData[conditionItem.modelKey])) {
                //   this.selfFormData[conditionItem.modelKey] = ''
                // } else if (isNumber(formData[conditionItem.modelKey])) {
                //   this.selfFormData[conditionItem.modelKey] = 0
                // } else {
                //   this.selfFormData[conditionItem.modelKey] = ''
                // }
                conditionResp = false
                ElMessage({
                  showClose: true,
                  message: conditionItem.message || '表单逻辑条件不满足！',
                  type: 'error',
                })
              }
            }
          })
        }

        return conditionResp
      },
    },
  })
</script>
